package com.example.base.mvvm

import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.blankj.utilcode.util.SPUtils
import com.example.base.net.Const
import com.example.base.net.Res
import com.example.base.net.Res2
import kotlinx.coroutines.launch

open class BaseViewModel : ViewModel() {
    //通用的失败的livedata
    val onFailed by lazy { MutableLiveData<Throwable>() }

    fun executeNetWork(
        //suspend挂起方法，也就是apiservice中的请求方法（）->代表挡墙参数是一个方法，Res代表当前方法的返回值
        s: suspend () -> Res,
        //成功的LIveData，会把s的返回值中的values添加到success中
        success: (String) -> Unit,
        //失败的LiveData，会把失败的信息（Throwable)直接传递到通用的onfailed的pastValue方法中
        failed: (Throwable) -> Unit = onFailed::postValue,
        okCode: Int = 200
    ) {
        viewModelScope.launch {
            try {
                //发起网络请求，invoke就是调用的意思，当期就是调用一次挂起方法，让他产生返回值res
                val res = s.invoke()
                SPUtils.getInstance().put(Const.PARAM_HOME, res.home)
                Log.i("TagA", "res:$res")
                if (res.statuesCode.toInt() == okCode) {
                    //如果网络请求成功为200，就把通用的res中的values给成功的LIveData赋值
                    success(res.values)
                } else {
                    //如果失败，则吧错误信息包一层exception，存放到失败的live
                    failed(Exception(res.msg))
                }
            } catch (e: Exception) {
                failed(e)
            }
        }
    }

    fun <T> executeNetWork2(
        //suspend挂起方法，也就是apiservice中的请求方法（）->代表挡墙参数是一个犯法，Res代表当前方法的返回值
        s: suspend () -> Res2<T>,
        //成功的LIveData，会把s的返回值中的values添加到success中
        success: (T) -> Unit,
        //失败的LiveData，会把失败的信息（Throwable)直接传递到通用的onfailed的pastValue方法中
        failed: (Throwable) -> Unit = onFailed::postValue,
        okCode: Int = 200
    ) {
        viewModelScope.launch {
            try {
                //发起网络请求，invoke就是调用的意思，当期就是调用一次挂起方法，让他产生返回值res
                val res2 = s.invoke()
                Log.i("TagA", "res:$res2")
                if (res2.code == okCode) {
                    //如果网络请求成功为200，就把通用的res中的values给成功的LIveData赋值
                    success(res2.data)
                } else {
                    //如果失败，则吧错误信息包一层exception，存放到失败的live
                    failed(Exception(res2.message))
                }
            } catch (e: Exception) {
                failed(e)
            }
        }
    }

    fun <D> executeDb(
        s: suspend () -> D,
        complete: (D) -> Unit,
        failed: (Throwable) -> Unit = onFailed::postValue
    ) {
        viewModelScope.launch {
            try {
                complete(s.invoke())
            } catch (e: Exception) {
                failed(e)
            }
        }
    }
}

